/**
 * 
 */
package com.sgv.model.persistence;

import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;

import com.archtecture.control.enums.Mensagem;
import com.archtecture.control.exceptions.NegocioException;
import com.sgv.model.entities.CaixaModel;
import com.sgv.model.entities.ItemCompraModel;
import com.sgv.model.entities.ItemVendaModel;
import com.sgv.model.entities.ProdutoModel;
import com.sgv.model.entities.VendaModel;

/**
 * @author Enir F Silva Ferraz
 *
 */

@Stateless(name = SGVCaixaFacadeLocal.JNDI_NAME)
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class SGVCaixaFacadeBean implements SGVCaixaFacadeLocal {

	@PersistenceContext(unitName = "SGV_PU")
	EntityManager manager;

	@EJB
	private UsuarioFacadeLocal segurancaFacade;

	@Override
	public CaixaModel obterUltimoCaixa() {

		StringBuilder lJPQL = new StringBuilder();

		lJPQL.append("SELECT caixa FROM ").append(CaixaModel.class.getSimpleName()).append(" caixa ");
		lJPQL.append("WHERE caixa.dataFechamento IS NULL ");
		lJPQL.append("ORDER BY caixa.dataAbertura DESC");

		try {
			return (CaixaModel) manager.createQuery(lJPQL.toString()).setMaxResults(1).getSingleResult();
		}
		catch (NoResultException e) {
			return null;
		}
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void abrirCaixa(CaixaModel pCaixa) throws NegocioException {

		pCaixa.setDataAbertura(Calendar.getInstance().getTime());
		pCaixa.setResponsavelAbertura(segurancaFacade.obterUsuarioLogado());

		manager.persist(pCaixa);
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void fecharCaixa(CaixaModel pCaixa) throws NegocioException {

		VendaModel lVenda = obterVendaAbertaPorUsuario();

		if (lVenda != null) {
			throw new NegocioException(Mensagem.ERRO_FECHAR_CAIXA_VENDA_ABERTA);
		}

		pCaixa.setDataFechamento(Calendar.getInstance().getTime());
		pCaixa.setResponsavelFechamento(segurancaFacade.obterUsuarioLogado());

		manager.merge(pCaixa);
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void inserirItemCompra(ItemCompraModel pItem) throws NegocioException {

		ProdutoModel lProduto = manager.find(ProdutoModel.class, pItem.getProduto().getCodigo());
		lProduto.setQuantidadeEstoque(lProduto.getQuantidadeEstoque() + pItem.getQuantidadeComprada());
		manager.merge(lProduto);

		manager.persist(pItem);

	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void excluirItemCompra(ItemCompraModel pItem) throws NegocioException {

		ProdutoModel lProduto = manager.find(ProdutoModel.class, pItem.getProduto().getCodigo());
		lProduto.setQuantidadeEstoque(lProduto.getQuantidadeEstoque() - pItem.getQuantidadeComprada());

		if (lProduto.getQuantidadeEstoque() < 0) {
			lProduto.setQuantidadeEstoque(0);
		}

		manager.merge(lProduto);

		manager.remove(manager.find(ItemCompraModel.class, pItem.getCodigo()));

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ProdutoModel> obterProdutos(String pNome) {

		StringBuilder lJPQL = new StringBuilder();

		lJPQL.append("SELECT produto FROM ").append(ProdutoModel.class.getSimpleName()).append(" produto ");

		if (isANumber(pNome)) {
			lJPQL.append("WHERE produto.codigo LIKE '").append(pNome).append("' ");
		}
		else {
			lJPQL.append("WHERE produto.nome LIKE '%").append(pNome).append("%' ");
		}

		lJPQL.append("ORDER BY produto.nome ASC");

		return manager.createQuery(lJPQL.toString()).setMaxResults(50).getResultList();
	}

	private boolean isANumber(String pNome) {

		try {
			Integer.parseInt(pNome);
			return true;
		}
		catch (NumberFormatException e) {
			return false;
		}

	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void salvarItemVenda(VendaModel pVenda, ItemVendaModel pItemVenda) throws NegocioException {

		if (pVenda.getCodigo() == null) {

			pVenda.setCaixa(obterUltimoCaixa());
			if (pVenda.getCaixa() == null) {
				throw new NegocioException(Mensagem.WARN_VENDA_CAIXA_NAO_CADASTRADO);
			}

			pVenda.setDtInicio(Calendar.getInstance().getTime());
			pVenda.setAtendente(segurancaFacade.obterUsuarioLogado());
			manager.persist(pVenda);
		}

		if (pItemVenda.getProduto().isPossuiNovoValor()) {
			ProdutoModel lProduto = manager.find(ProdutoModel.class, pItemVenda.getProduto().getCodigo());
			lProduto.setValorVenda(pItemVenda.getProduto().getValorVenda());
			lProduto.setQuantidadeEstoque(lProduto.getQuantidadeEstoque() - pItemVenda.getQuantidadeVendida());
			lProduto.setFlPreCadastro("S");
			manager.merge(lProduto);
		}

		pItemVenda.setVenda(pVenda);
		manager.persist(pItemVenda);

		pVenda.setVlTotalVenda(pVenda.getVlTotalVenda() != null ? pVenda.getVlTotalVenda() : 0D + pItemVenda.getTotalVenda());
		manager.merge(pVenda);
	}

	@SuppressWarnings("unchecked")
	@Override
	public VendaModel obterVendaAbertaPorUsuario() throws NegocioException {

		StringBuilder lJPQL = new StringBuilder();

		lJPQL.append("SELECT venda FROM ").append(VendaModel.class.getSimpleName()).append(" venda ");
		lJPQL.append("JOIN FETCH venda.listItemVenda listItemVenda ");
		lJPQL.append("JOIN FETCH venda.atendente atendente ");
		lJPQL.append("WHERE venda.dtFim IS NULL ");

		if (segurancaFacade.verificarPermissao("ADMINISTRADOR")) {

			try {

				List<VendaModel> vendasAbertas = manager.createQuery(lJPQL.toString()).getResultList();

				if (!vendasAbertas.isEmpty()) {
					return (VendaModel) vendasAbertas.iterator().next();
				}
				else {
					return null;
				}

			}
			catch (NoResultException e) {
				return null;
			}
		}

		else {

			lJPQL.append(" AND atendente.codigo = " + segurancaFacade.obterUsuarioLogado().getCodigo());

			try {
				return (VendaModel) manager.createQuery(lJPQL.toString()).getSingleResult();
			}
			catch (NoResultException e) {
				return null;
			}
		}

	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void excluirItemVenda(ItemVendaModel pItemVenda) {

		ItemVendaModel lItemVenda = manager.find(ItemVendaModel.class, pItemVenda.getCodigo());

		ProdutoModel lProduto = manager.find(ProdutoModel.class, lItemVenda.getProduto().getCodigo());
		lProduto.setQuantidadeEstoque(lProduto.getQuantidadeEstoque() + lItemVenda.getQuantidadeVendida());
		manager.merge(lProduto);

		manager.remove(lItemVenda);
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void concluirVenda(VendaModel pVenda) {

		VendaModel lVenda = manager.find(VendaModel.class, pVenda.getCodigo());
		lVenda.setDtFim(Calendar.getInstance().getTime());
		lVenda.setVlPagamento(pVenda.getVlPagamento());
		manager.merge(lVenda);

		CaixaModel lCaixa = lVenda.getCaixa();
		lCaixa.setVlrVendaAtual(lCaixa.getVlrVendaAtual() != null ? lCaixa.getVlrVendaAtual() : 0D + lVenda.getVlTotalVenda());
		lCaixa.setVlrArrecadado(lCaixa.getVlrArrecadado() != null ? lCaixa.getVlrArrecadado() : 0D + lVenda.getVlPagamento());
		manager.merge(lCaixa);
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void cancelarVenda(VendaModel pVenda) {

		VendaModel lVenda = manager.find(VendaModel.class, pVenda.getCodigo());

		for (ItemVendaModel lItemLoop : lVenda.getListItemVenda()) {
			excluirItemVenda(lItemLoop);
		}

		manager.remove(lVenda);
	}
}
